iT邦幫忙

2024 iThome 鐵人賽

DAY 22
0
Modern Web

剛入行就一人重新打造公司前端系統?系列 第 22

Day 22 - 瀏覽器的重繪機制與網頁渲染

  • 分享至 

  • xImage
  •  

學習 React 的過程中,常常會碰到各種與「渲染」相關的名詞與概念,尤其在試圖理解「React 如何與瀏覽器互動」以及「各種不同渲染術語」時,總覺得有點卡卡的,今天這篇會試著從不同角度整理出這些概念。

1. 瀏覽器運作原理(Repaint 與 Reflow)

  • 瀏覽器的渲染過程

    image.png

    圖片來源 https://gist.github.com/faressoft

    1. 從 HTML 檔案構建 DOM Tree,與從 CSS 檔案構建 CSSOM(CSS Object Model)Tree。
    2. 將 DOM Tree 與 CSSOM Tree 合併為 Render Tree(如何合併可參考 web.dev)。
    3. 佈局(Layout)時計算每個元素的確切位置和大小。
    4. 繪製(Paint)時將 Render Tree 繪製到螢幕上。
    5. 合成 (compositing) 這步驟是為了當文件的各個部分在不同的圖層中繪製且彼此重疊時,需要進行合成以確保它們以正確的順序繪製到螢幕上並正確呈現內容(參考 MDN - compositing)。
    • Reflow 與 Repaint 會在佈局與繪製時觸發:
      • Reflow:當 DOM 的結構發生變化或尺寸、位置改變時(如加入新元素、改變元素大小),瀏覽器必須重新計算佈局,進行 reflow。這會影響整個頁面的佈局,成本高於 repaint。
      • Repaint:當 DOM 元素的樣式改變但不影響佈局時,例如顏色或背景變更,瀏覽器會進行 repaint,只會重繪畫面,而不需要重新計算佈局。
  • 認識Reflow和Repaint 這篇講的很清楚,有提到簡單來說:

    需要重新計算DOM節點 → Reflow
    更改樣式重新繪製畫面,不涉及畫面排版→ Repaint

在 React 中,如何思考 Repaint 與 Reflow?

  • 昨天的文章中有提到 Virtual DOM 與重新渲染的概念,React 會先利用 Virtual DOM 的方式來計算最小的改變並更新 DOM。當 DOM 發生變化時,就可能引起 Reflow 或 Repaint。
  • 補充一下,除了 Virtual DOM 外,React 有不少內建機制與最佳化策略來減少 DOM 操作的次數,以達到不必要的 Reflow 和 Repaint,像是 Batch Updates、useMemouseCallback 的使用、Concurrent Mode 等。

2. CSR、SSR、SSG 的差異

  • 客戶端渲染(CSR, Client-Side Rendering):

    所有的 JavaScript 和 HTML 在一開始都是由瀏覽器下載,然後由 JavaScript 執行來生成畫面,像是典型的 SPA 應用程式。好處是使用者操作會很流暢,缺點是初次載入的時間較長,SEO 也不太好。

  • 伺服器端渲染(SSR, Server-Side Rendering):

    頁面一開始由伺服器生成完整的 HTML,再送到客戶端。當使用者請求一個頁面時,伺服器先執行 React 程式碼來組合出 HTML 結構並發送,這樣頁面在瀏覽器中能更快看到完整內容。它解決了 CSR 的 SEO 問題,但每次請求都會消耗伺服器資源。

  • 靜態網站生成(SSG, Static Site Generation):

    在 build 時(編譯階段)預先生成所有 HTML 靜態頁面,並且部署到 CDN 上。這樣的做法讓網站有最快的載入速度,適合用在內容不常變動的網站上(像是部落格或文檔)。但如果頁面內容需要頻繁更新,靜態生成就不太合適了。

3. 靜態渲染與動態渲染的差異

靜態渲染和動態渲染之間的差異,在於頁面內容是「固定的」還是「根據需求變動的」。

  • 靜態渲染(Static Rendering)
    指的是在頁面載入前,所有的 HTML 就已經被完全生成和渲染。最典型的例子就是靜態網站生成器(如 Gatsby),在 build 時預先生成所有 HTML。好處是載入速度快,不需要等到 JavaScript 執行後才看到內容。
  • 動態渲染(Dynamic Rendering)
    指的是頁面在用戶每次請求時都會根據當前狀態動態生成。例如根據使用者的登入狀態、購物車內容來生成頁面。

如何區分靜態渲染與動態渲染?

這取決於頁面的內容是否需要動態更新。例如,顯示商品列表的頁面,如果使用 SSG 生成靜態頁面,那麼所有訪客看到的都是相同的內容(靜態渲染)。而若使用 SSR 或 CSR,頁面內容則可能根據使用者的互動或資料狀態變動(動態渲染)。

4. 其他渲染術語:Rehydration、Prerendering

  • Rehydration(再水化)
    當伺服器端渲染的靜態 HTML 被加載到客戶端時,React 會「激活」這些靜態內容,將其轉換成可交互的 React 元件。這個過程被稱為再水化(Rehydration),它允許伺服器渲染和客戶端渲染無縫結合。
  • Prerendering(預渲染)
    預渲染是一種將頁面預先生成為靜態 HTML 的方式。與 SSG 類似,但它更多地應用於在第一次訪問前提前渲染常見頁面。這樣可以提升首次載入速度。

如何在 React 中理解這些術語?

理解這些術語的核心在於理解渲染的時機和位置。例如,Rehydration 更多的是在 CSR 和 SSR 結合的情境下出現,而 Prerendering 則是在靜態頁面的優化策略中使用。知道它們的存在,有助於你更好地選擇適合專案需求的渲染策略。

如何連接各種渲染術語?

搞懂這些概念最困難的部分,在於它們有時會交錯使用。例如,靜態渲染可以用在 SSG 的情境中,而 SSR 則屬於 動態渲染 的一種情況。以下是一個整理圖,幫助你更好地理解這些概念之間的連結:

渲染類型 生成時間 生成位置 例子
CSR 使用者請求時 客戶端(瀏覽器) React SPA
SSR 使用者請求時 伺服器 Next.js 的 getServerSideProps 或是 server component
SSG 部署(或建置)時 伺服器 Gatsby、Next.js 的靜態生成
靜態渲染 部署(或建置)時 伺服器 Gatsby、Hexo 靜態頁面
動態渲染 使用者請求時 伺服器 PHP、Node.js

參考資料


上一篇
Day 21 - 對 React 一見鍾情的故事(技術名詞有解釋別擔心)
下一篇
Day 23 - 「元件」與 useState 使用技巧
系列文
剛入行就一人重新打造公司前端系統?27
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言